/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package maxent.mr.trainer;

import edu.stanford.nlp.io.PrintFile;
import edu.stanford.nlp.tagger.maxent.TaggerConfig;
import edu.stanford.nlp.util.Timing;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.Date;
import maxent.mr.io.DictionaryReader;
import maxent.mr.io.ObjectWriter;
import maxent.mr.io.TagTokenReader;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.util.ToolRunner;
import stanford.tagger.LambdaSolveTagger;
import stanford.tagger.Problem;
import stanford.tagger.StanfordTagger;
import stanford.tagger.TaggerFeatures;
import stanford.tagger.TrainerExperiments;

/**
 *
 * @author hadoop
 */
public class MaxentTrainer {

    protected static String TEMP_PATH = "temp";
    
    public static void main(String []args){

        if(args.length != 3){
            System.err.println("Usage: MaxentTrainer <properties file> <train file> <model name>");
            System.exit(-1);
        }

        String[] configParam = new String[6];
        configParam[0] = "-prop";
        configParam[1] = args[0];
        configParam[2] = "-trainFile";
        configParam[3] = args[1];
        configParam[4] = "-model";
        configParam[5] = args[2];
                
        // initialize the configuration for Stanford tagger
        TaggerConfig taggerConfig = new TaggerConfig(configParam);
        runTraining(taggerConfig);
        
        

    }

    private static void runTraining(TaggerConfig taggerConfig){

        Date now = new Date();        

        System.err.println("## tagger training invoked at " + now + " with arguments:");
        taggerConfig.dump();
        Timing tim = new Timing();
        try {
          PrintFile log = new PrintFile(taggerConfig.getModel() + ".props");
          log.println("## tagger training invoked at " + now + " with arguments:");
          taggerConfig.dump(log);
          log.close();

          trainModel(taggerConfig);
          tim.done("Training POS Tagger");
          
          } catch(Exception e) {
              System.err.println("An error occurred while training a new tagger.");
              e.printStackTrace();
          }
    }

    private static void trainModel(TaggerConfig config) throws Exception{

        String modelName = config.getModel();
        StanfordTagger trainer = new StanfordTagger(config);

        String inputDir = getPath(config.getFile());
        String tagtokenOutputDir = inputDir+"-tagtoken";
        String dictionaryOutputDir = inputDir+"-dictionary";

        String[] args = new String[2];
        args[0] = inputDir;
        args[1] = config.getTagSeparator();

        int res = ToolRunner.run(new Configuration(), new TagTokenRunner(), args);
        res = ToolRunner.run(new Configuration(), new DictionaryRunner(), args);

        TagTokenReader ttReader = new TagTokenReader(tagtokenOutputDir);
        ttReader.read();
        trainer.setTagTokens(ttReader.getTagToken()) ;
        DictionaryReader dictReader = new DictionaryReader(dictionaryOutputDir);
        dictReader.read();
        trainer.setDictionary(dictReader.getDict());
        
        // read training data and generate feature
        TrainerExperiments samples = new TrainerExperiments(config, trainer);
        TaggerFeatures feats = samples.getTaggerFeatures();
        System.err.println("Samples from " + config.getFile());
        System.err.println("Number of features: " + feats.size());

        // generate problem
        Problem p = new Problem(samples, feats);

        // initialize for iis
        LambdaSolveTagger prob = new LambdaSolveTagger(p, 0.0001, 0.00001, trainer.getFnumArr());
        trainer.setProb(prob);


        System.out.println("Starting Job IIS");

//        String[] arg = new String[0];
//        int resi = ToolRunner.run(new Configuration(), new IISRunner(config.getIterations(), prob),arg);

        prob.improvedIterative(config.getIterations());


        if (prob.checkCorrectness()) {
          System.out.println("Model is correct [empirical expec = model expec]");
        } else {
          System.out.println("Model is not correct");
        }
        trainer.saveModel(modelName, config);

        }

    private static String getPath(String filename){
        int index = filename.lastIndexOf("/");
        return filename.substring(0,index);
    }

}
